home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / libs / sphigs / sph_mac.hqx / SRGP port to 5.0 (compressed) / SRGP_SPHIGS Root / MacSPHIGS / sph_clip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-13  |  10.0 KB  |  397 lines

  1. #include "HEADERS.h"
  2.    /**********************
  3.     *
  4.     File                 * clip.c
  5.     * object clipping unit
  6.     *
  7.     * takes all the objects in the list and clips them against
  8.     * the front and back planes
  9.     *
  10.     * calculates bounds in obj
  11.     * may add points to global list
  12.     *
  13.     *********************************************************/
  14.    
  15.    /**********************
  16.     *
  17.     Includes             *
  18.     *
  19.     *********************************************************/
  20.    
  21. #include <stdio.h>
  22. #include <assert.h>
  23. #include <math.h>
  24.    
  25. #include "sphigslocal.h"
  26.    
  27.    
  28.    /**********************
  29.     *
  30.     Prototypes           *
  31.     *
  32.     *********************************************************/
  33.    
  34. void bound(view_spec *vs, obj *current );
  35.  
  36. vertex_index add_global_point(view_spec *vs, MAT3hvec p );
  37.  
  38. #define FRONT 1
  39. #define BACK  2
  40.  
  41. static void clip_generic (view_spec *vs,  obj *current, double wall, int WHICH);
  42. static void interpolate_point( MAT3hvec p1, MAT3hvec p2, double z, MAT3hvec p3 );
  43.  
  44.  
  45. #define clip_front(V,C,W)   clip_generic((V),(C),(W), FRONT)
  46. #define clip_back(V,C,W)   clip_generic((V),(C),(W), BACK)
  47.  
  48. #include "sph_clip.proto.h"
  49. static void clip_generic(view_spec *, obj *, double, int);
  50. static void interpolate_point(MAT3hvec, MAT3hvec, double, MAT3hvec);
  51.  
  52. /**********************
  53.  *
  54.  Function             * clip
  55.  *
  56.  * filters the list of objects by clipping the objects
  57.  * against the front and back planes
  58.  *
  59.  *********************************************************/
  60.  
  61. void SPH__clip (view_spec *vs)
  62. {
  63.    obj *              current;
  64.    obj *              prev;
  65.    MAT3hvec           min;
  66.    MAT3hvec           max;
  67.    MAT3hvec           previous;
  68.    double             front;
  69.    double             back;
  70.    MAT3hvec *         uvnVertices;
  71.    
  72.    assert( vs != NULL );
  73.    front = vs->frontPlaneDistance;
  74.    back = vs->backPlaneDistance;
  75.    
  76.    if( vs->objects == NULL )
  77.       return;
  78.    
  79.    assert( vs->vm_matrix != NULL );
  80.    assert( vs->uvnVertices != NULL );
  81.    uvnVertices = vs->uvnVertices;
  82.    assert( back < front );
  83.    
  84.    prev = NULL;
  85.    current = vs->objects;
  86.    while( current != NULL ) {
  87.       
  88.       assert( current->next != current );
  89.       
  90.       bound(vs, current );
  91.       assert( current->min[X] <= current->max[X] );
  92.       assert( current->min[Y] <= current->max[Y] );
  93.       assert( current->min[Z] <= current->max[Z] );
  94.       
  95.       MAT3_COPY_VEC( min, current->min );
  96.       MAT3_COPY_VEC( max, current->max );   /* saves the dereference each time we need it */
  97.       
  98.       /* remove obj if z bounds are behind "back" or in front of "front" */
  99.       
  100.       /* this will take care of points and text */
  101.       
  102.       if( max[Z] < back || min[Z] > front ) {
  103.      if( prev == NULL )
  104.         vs->objects = current->next;
  105.      else
  106.         prev->next = current->next;
  107.      current = current->next;
  108.      continue;
  109.       }
  110.       
  111.       /* only clip object if it's intersecting the front or back plane */
  112.       
  113.       if( max[Z] > front || min[Z] < back ) {
  114.      
  115.      /* handle line intersection with front and back planes */
  116.      
  117.      if( current->type == objLine ) {
  118.         
  119.         /* special case lines parallel to X-Y */
  120.         
  121.         if( min[X] == max[X] || min[Y] == max[Y] ) {
  122.            min[Z] = MAX( min[Z], back );
  123.            max[Z] = MIN( max[Z], front );
  124.            MAT3_COPY_VEC( current->min, min );
  125.            MAT3_COPY_VEC( current->max, max );
  126.            
  127.         } else {
  128.            if( max[Z] > back && back > min[Z] ) {
  129.           fprintf (stderr, "CALL TO interpolate_point IS WEIRD (clip.c,1)\n");
  130.           sleep(15);
  131.           exit(1);
  132.           /* interpolate_point( max[Z], min[Z], back, min[Z] ); */
  133.            }
  134.            if( max[Z] > front && front > min[Z] ) {
  135.           fprintf (stderr, "CALL TO interpolate_point IS WEIRD (clip.c,2)\n");
  136.           sleep(15);
  137.           exit(1);
  138.           /* interpolate_point( min[Z], max[Z], back, max[Z] ); */
  139.            }
  140.         }
  141.         
  142.      } else if( current->type == objFace ) {
  143.         
  144.         /* handle plane intersection with front and back planes */
  145.         
  146.         assert( current->data.face.numPoints >= 3 );
  147.         
  148.         if( max[Z] > front )
  149.            clip_front( vs, current, front );
  150.         
  151.         if( min[Z] < back )
  152.            clip_back( vs, current, back );
  153.         
  154.      }
  155.       }
  156.       
  157.       prev = current;
  158.       current = current->next;
  159.    }
  160. }
  161.  
  162. /**********************
  163.  *
  164.  Function             * bound
  165.  *
  166.  * calculates the uvn bounding cube for the object
  167.  *
  168.  *********************************************************/
  169.  
  170. void bound(view_spec *vs, obj *current )
  171.  
  172. {
  173.    register int       i;
  174.    MAT3hvec           p;
  175.    MAT3hvec           max;
  176.    MAT3hvec           min;
  177.    
  178.    assert( vs != NULL );
  179.    assert( vs->uvnVertices != NULL );
  180.    assert( current != NULL );
  181.    
  182.    switch( current->type ) {
  183.     case objFace:
  184.       
  185.       max[X] = max[Y] = max[Z] = -HUGE_VAL;
  186.       min[X] = min[Y] = min[Z] = HUGE_VAL;
  187.       
  188.       for( i = 0; i < current->data.face.numPoints; i++ ) {
  189.      MAT3_COPY_VEC (p, 
  190.             (vs->uvnVertices)
  191.                [current->data.face.points[i]] );
  192.      if( p[X] > max[X] )
  193.         max[X] = p[X];
  194.      if( p[Y] > max[Y] )
  195.         max[Y] = p[Y];
  196.      if( p[Z] > max[Z] )
  197.         max[Z] = p[Z];
  198.      
  199.      if( p[X] < min[X] )
  200.         min[X] = p[X];
  201.      if( p[Y] < min[Y] )
  202.         min[Y] = p[Y];
  203.      if( p[Z] < min[Z] ) 
  204.         min[Z] = p[Z];
  205.       }
  206.       MAT3_COPY_VEC( current->min, min );
  207.       MAT3_COPY_VEC( current->max, max );
  208.       break;
  209.       
  210.     case objLine:
  211.       for (i=X; i<=Z; i++) {
  212.          min[i] = 
  213.         MIN (current->data.line.end1[i], current->data.line.end2[i]);
  214.      max[i] = 
  215.         MAX ( current->data.line.end1[i], current->data.line.end2[i]);
  216.       }
  217.       break;
  218.       
  219.     case objPoint:
  220.       MAT3_COPY_VEC( current->max, current->min );
  221.       break;
  222.       
  223.     case objText:
  224.       current->max[Z] = current->min[Z];
  225.       break;
  226.       
  227.    }
  228. }
  229.  
  230.  
  231.  
  232. static void clip_generic (view_spec *vs,  obj *current, double wall, int WHICH)
  233. {
  234.    int                last_zone;
  235.    int                current_zone;
  236.    int                index1, index2;
  237.    MAT3hvec           new_point;
  238.    MAT3hvec           last_point;
  239.    MAT3hvec           current_point;
  240.    int                new_global_index;
  241.    vertex_index *     new_face_points;
  242.    vertex_index *     points;
  243.    MAT3hvec *         uvnVertices;
  244.    int                i;
  245.    boolean            final_point, flag;
  246.    
  247.    assert( vs != NULL );
  248.    assert( vs->uvnVertices != NULL );
  249.    assert( current != NULL );
  250.    
  251.    uvnVertices = vs->uvnVertices;
  252.    
  253.    /* go through all the points */
  254.    
  255.    index2 = 0;
  256.    index1 = 0;
  257.    
  258.    new_face_points = (vertex_index *) 
  259.       FALLOCalloc(vs->objectChunk, 
  260.           sizeof(vertex_index) * 
  261.           (current->data.face.numPoints+2), FALLOC__DONT_ZERO);
  262.    assert( new_face_points != NULL );
  263.    
  264.    points = & current->data.face.points[0];
  265.    assert( points != NULL );
  266.    
  267.    MAT3_COPY_VEC( last_point, uvnVertices[ points[ index1 ] ] );
  268.  
  269.    flag = FALSE;
  270.    if (WHICH == BACK) {   
  271.       if (last_point[Z] < wall) {last_zone = -1; flag=TRUE;}
  272.    }
  273.    else {
  274.       if (last_point[Z] > wall) {last_zone = 1; flag=TRUE;}
  275.    }
  276.    if ( ! flag) {
  277.       last_zone = 0;
  278.       new_face_points[ index2 ] = points[ index1 ];
  279.       index2 ++;
  280.    }
  281.    
  282.    final_point = FALSE;
  283.    for( index1 = 1; index1 <= current->data.face.numPoints && ! final_point; index1 ++ ) {
  284.       
  285.       if( index1 == current->data.face.numPoints ) {
  286.      final_point = TRUE;
  287.      MAT3_COPY_VEC( current_point, uvnVertices[ points[ 0 ] ] );
  288.       } else
  289.      MAT3_COPY_VEC( current_point, uvnVertices[ points[ index1 ] ] );
  290.       
  291.       flag = FALSE;
  292.       if (WHICH == BACK) {   
  293.          if (current_point[Z] < wall) {current_zone = -1; flag=TRUE;}
  294.       }
  295.       else {
  296.          if (current_point[Z] > wall) {current_zone = 1; flag=TRUE;}
  297.       }
  298.       if ( ! flag)
  299.      current_zone = 0;
  300.       
  301.  
  302.       if( current_zone != last_zone ) {
  303.      interpolate_point( last_point, current_point, wall, new_point );
  304.      new_global_index = add_global_point( vs, new_point );
  305.      new_face_points[ index2 ] = new_global_index;
  306.      index2 ++;
  307.       }
  308.       
  309.       if( current_zone == 0 && ! final_point ) {
  310.      new_face_points[ index2 ] = points[ index1 ];
  311.      index2 ++;
  312.       }
  313.       
  314.       MAT3_COPY_VEC( last_point, current_point );
  315.       last_zone = current_zone;
  316.    }
  317.    
  318.    current->data.face.points = new_face_points;
  319.    current->data.face.numPoints = index2;
  320.    
  321. }
  322.  
  323.  
  324.  
  325.  
  326. /**********************
  327.  *
  328.  Function             * interpolate_point
  329.  *
  330.  * given two endpoints, returns the point at z
  331.  *
  332.  *********************************************************/
  333.  
  334. static void interpolate_point( MAT3hvec p1, MAT3hvec p2, double z, MAT3hvec p3 )
  335. {
  336.    double             yz_slope;
  337.    double             xz_slope;
  338.    
  339.    yz_slope = ( p2[Y] - p1[Y] ) / ( p2[Z] - p1[Z] );
  340.    xz_slope = ( p2[X] - p1[X] ) / ( p2[Z] - p1[Z] );
  341.    
  342.    p3[Z] = z;
  343.    p3[X] = p1[X] + xz_slope * ( z - p1[Z] );
  344.    p3[Y] = p1[Y] + yz_slope * ( z - p1[Z] );
  345. }
  346.  
  347.  
  348. /**********************
  349.  *
  350.  Function             * add_global_point
  351.  *
  352.  * adds a point to the global list of points
  353.  * returns the index of the point in the array
  354.  * also adds the perspectivized point into its array
  355.  *
  356.  *********************************************************/
  357.  
  358. vertex_index add_global_point(view_spec *vs, MAT3hvec p )
  359.  
  360. {
  361.    assert( vs != NULL );
  362.    assert( vs->uvnVertices != NULL );
  363.    assert( vs->npcVertices != NULL );
  364.    assert( vs->vertexArraySize != 0 );
  365.    assert( vs->vertexCount <= vs->vertexArraySize );
  366.    
  367.    if( vs->vertexCount == vs->vertexArraySize ) {
  368.       vs->vertexArraySize /= 2;
  369.       vs->vertexArraySize *= 3;
  370.       vs->uvnVertices = 
  371.      (MAT3hvec*) 
  372.         realloc (vs->uvnVertices, 
  373.              (MALLOCARGTYPE)(vs->vertexArraySize*sizeof(MAT3hvec)));
  374.       if (vs->uvnVertices == NULL) 
  375.      SPH__error (ERR_MALLOC);
  376.       vs->npcVertices = 
  377.      (MAT3hvec *) 
  378.         realloc (vs->npcVertices, 
  379.              (MALLOCARGTYPE)(vs->vertexArraySize*sizeof(MAT3hvec)));
  380.       if (vs->npcVertices == NULL) 
  381.      SPH__error (ERR_MALLOC);
  382.    }
  383.    
  384.    MAT3_COPY_VEC( (vs->uvnVertices)[ vs->vertexCount ], p );
  385.    ((vs->uvnVertices)[ vs->vertexCount ])[3] = 1;
  386.    
  387.    MAT3mult_hvec
  388.       (vs->npcVertices[ vs->vertexCount ], 
  389.        vs->uvnVertices[ vs->vertexCount ],
  390.        vs->vm_matrix, 1 );
  391.    (vs->npcVertices[ vs->vertexCount ])[Z] *= -1;
  392.    
  393.    vs->vertexCount ++;
  394.    
  395.    return( vs->vertexCount - 1 );
  396. }
  397.